package cn.edu.gzgs.util;

import cn.edu.gzgs.vo.WebOfficeVO;
import com.aliyun.imm20200930.Client;
import com.aliyun.imm20200930.models.GenerateWebofficeTokenRequest;
import com.aliyun.imm20200930.models.GenerateWebofficeTokenResponse;
import com.aliyun.oss.*;
import com.aliyun.tea.*;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;


import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.Date;

@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    private String regionId;
    // IMM预览相关常量
    private String projectName;
    private String immEndpoint;

    /**
     * 文件上传
     *
     * @param bytes
     * @param objectName
     * @return
     */
    public String upload(byte[] bytes, String objectName) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        log.info("文件上传到:{}", stringBuilder.toString());

        return stringBuilder.toString();
    }

    /**
     * 删除文件
     *
     * @param objectName
     */
    public void delete(String objectName) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 删除文件。
            ossClient.deleteObject(bucketName, objectName);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        log.info("文件 {} 已从OSS删除。", objectName);
    }


    /**
     * <b>description</b> :
     * <p>使用凭据初始化账号Client</p>
     * @return Client
     *
     * @throws Exception
     */
    public Client createClient() throws Exception {
        // 工程代码建议使用更安全的无AK方式，凭据配置方式请参见：https://help.aliyun.com/document_detail/378657.html。
        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        // Endpoint 请参考 https://api.aliyun.com/product/imm
        config.endpoint = immEndpoint;
        return new Client(config);
    }

    /**
     * 生成WebOffice链接和预览凭证信息，用于在线预览
     *
     * @param objectName 文件名或完整的OSS URL
     * @return WebOfficeVO 链接和预览凭证信息
     */
    public WebOfficeVO generateWebOfficePreviewUrl(String objectName) throws Exception {
//        String OSSURL = "oss://"+bucketName+"/"+objectName;
//        log.info("文件访问路径:{}", OSSURL);
        Client client = this.createClient();
        GenerateWebofficeTokenRequest generateWebofficeTokenRequest = new GenerateWebofficeTokenRequest()
                .setProjectName(projectName)
                .setSourceURI("oss://"+bucketName+"/"+objectName)//   oss://cya-springboot-01/bcabc3b9-31b4-4be6-a6ce-73bf90320584.pdf
                .setFilename(objectName) // bcabc3b9-31b4-4be6-a6ce-73bf90320584.pdf
                .setCachePreview(true)
                .setReferer("")
                .setUserData("")
                .setExternalUploaded(false);
        RuntimeOptions runtime = new RuntimeOptions();
        String webofficeURL = null;
        String accessToken = null;
        try {
            // 复制代码运行请自行打印 API 的返回值
            GenerateWebofficeTokenResponse generateWebofficeTokenResponse = client.generateWebofficeTokenWithOptions(generateWebofficeTokenRequest, runtime);
            webofficeURL = generateWebofficeTokenResponse.getBody().webofficeURL;
            accessToken = generateWebofficeTokenResponse.getBody().accessToken;
            log.info("webofficeURL:{}", webofficeURL);
            log.info("accessToken:{}", accessToken);
        } catch (TeaException error) {
            // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
            // 错误 message
            System.out.println(error.getMessage());
            // 诊断地址
            if (error.getData() != null) {
                System.out.println(error.getData().get("Recommend"));
            }
            com.aliyun.teautil.Common.assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
            // 错误 message
            System.out.println(error.getMessage());
            // 诊断地址
            if (error.getData() != null) {
                System.out.println(error.getData().get("Recommend"));
            }
            com.aliyun.teautil.Common.assertAsString(error.message);
        }

        WebOfficeVO webOfficeVO = new WebOfficeVO();
        webOfficeVO.setWebofficeURL(webofficeURL);
        webOfficeVO.setAccessToken(accessToken);
        return webOfficeVO;
    }


    
    /**
     * 生成文件的签名URL，用于下载
     *
     * @param objectName 文件名或完整的OSS URL
     * @param expireInSeconds URL有效期，单位秒
     * @return 签名URL
     * @throws Exception 如果生成URL过程中发生异常
     */
    public String generatePresignedDownloadUrl(String objectName, long expireInSeconds){
        // 1. 参数合法性校验
        if (objectName == null || objectName.trim().isEmpty()) {
            throw new IllegalArgumentException("objectName不能为空");
        }
        if (expireInSeconds <= 0) {
            throw new IllegalArgumentException("expireInSeconds必须大于0");
        }

        // 如果传入的是完整的OSS URL，则提取objectName
        if (objectName.startsWith("https://")) {
            String ossPrefix = "https://" + bucketName + "." + endpoint + "/";
            if (objectName.startsWith(ossPrefix)) {
                objectName = objectName.substring(ossPrefix.length());
            } else {
                throw new IllegalArgumentException("提供的URL不是有效的OSS URL");
            }
        }

        // 2. 初始化OSS客户端
        OSS ossClient = null;
        try {
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            // 显式声明使用 V4 签名算法
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
            CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);

            ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(regionId)
                .build();

            // 3. 设置URL过期时间
            Date expiration = new Date(System.currentTimeMillis() + expireInSeconds * 1000L);

            // 4. 创建预签名请求
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName);
            request.setExpiration(expiration);

            // 5. 设置为attachment，使浏览器下载文件
            request.addQueryParameter("response-content-disposition", "attachment; filename=\"" + objectName + "\"");

            // 6. 生成预签名URL
            URL presignedUrl = ossClient.generatePresignedUrl(request);
            log.info("为文件 {} 生成下载签名URL: {}", objectName, presignedUrl.toString());
            return presignedUrl.toString();

        } catch (OSSException oe) {
            log.error("生成下载签名URL时发生OSS异常: {}, 错误码: {}, 请求ID: {}", oe.getErrorMessage(), oe.getErrorCode(), oe.getRequestId());
            throw new RuntimeException("生成下载签名URL失败: " + oe.getErrorMessage());
        } catch (ClientException ce) {
            log.error("生成下载签名URL时发生客户端异常: {}", ce.getMessage());
            throw new RuntimeException("生成下载签名URL失败: " + ce.getMessage());
        } finally {
            // 7. 关闭OSS客户端
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }



//    /**
//     * 根据文件扩展名获取对应的Content-Type
//     *
//     * @param fileName 文件名
//     * @return 对应的Content-Type
//     */
//    private String getContentTypeByExtension(String fileName) {
//        String extension = "";
//        int lastDotIndex = fileName.lastIndexOf('.');
//        if (lastDotIndex > 0) {
//            extension = fileName.substring(lastDotIndex + 1).toLowerCase();
//        }
//
//        switch (extension) {
//            case "pdf":
//                return "application/pdf";
//            case "doc":
//            case "docx":
//                return "application/msword";
//            case "xls":
//            case "xlsx":
//                return "application/vnd.ms-excel";
//            case "ppt":
//            case "pptx":
//                return "application/vnd.ms-powerpoint";
//            case "jpg":
//            case "jpeg":
//                return "image/jpeg";
//            case "png":
//                return "image/png";
//            case "gif":
//                return "image/gif";
//            case "txt":
//                return "text/plain";
//            case "html":
//            case "htm":
//                return "text/html";
//            case "xml":
//                return "text/xml";
//            case "mp4":
//                return "video/mp4";
//            case "mp3":
//                return "audio/mpeg";
//            default:
//                return "application/octet-stream";
//        }
//    }
}
